#region Imports
using System;
using System.Data;
using System.Data.SqlClient;
using PHSRAG.Insight21.CDS;
using BO = PHSRAG.Insight21.BusinessObjects;
using DataAccess = PHSRAG.Utility.DataAccess;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
#endregion

namespace PHSRAG.Insight21.Humans
{
	/// <summary>
	/// Represents the binding between a person (who is not staffed to the study, 
	/// but has access to the protocol) and the study
	/// </summary>
	public class NonStaffPerson : BaseStudyPerson, ICloneable
	{
		#region Instance Variables (Private)

		private string comments;

		#endregion

		#region constants

		private const string NonStaffPersonKey = "NonStaffPerson_65420732-10F5-42cc-91ED-C5D6718FD4BB";
		
		#endregion

		#region Public Properties
		/// <summary>
		/// Cache Key uniquely identifies this object within the cache.
		/// </summary>
		/// <returns>the unique string for this object.</returns>
		public override string CacheKey()
		{
			return NonStaffPersonKey;
		}

		/// <summary>
		/// The reason why this person was granted access to the study
		/// </summary>
		public string Comments
		{
			get{ return comments; }
			set{ SetDirty(ref comments, value); }
		}

		/// <summary>
		/// Gets the name of the person's primary organization, available here for databinding purposes
		/// </summary>
		public string OrganizationName
		{
			get{ return Person.OrganizationName; }
		}

		/// <summary>
		/// Gets the Id of the person's primary organization, available here for databinding purposes
		/// </summary>
		public int OrganizationId
		{
			get{ return Person.OrganizationId; }
		}

		#endregion

        object ICloneable.Clone()
        {
            return Clone();
        }

        public NonStaffPerson Clone()
        {
            NonStaffPerson clone = (NonStaffPerson)MemberwiseClone();
            clone.Id = 0;
            clone.IsClone = true;
            clone.Dirty = true;
            return clone;
        }

		/// <summary>
		/// Initializes the base with the specified cache policy and sets the state from
		/// the row passed in
		/// </summary>
		/// <param name="cachePolicy">policy to use to cache this instance</param>
		/// <param name="row">row to set the state of the instance from</param>
        /// <param name="defaultPermissionLevel">permission level to set if one doesn't exist</param>
		public NonStaffPerson(ICachePolicy cachePolicy, DataRow row, int defaultPermissionLevel) : base(cachePolicy, row)
		{
			if (row.Table.Columns.Contains("Comments"))
			{
				object o = row["Comments"];
				comments = (o == DBNull.Value) ? string.Empty : (string)o;
			}

            if (PermissionLevel == 0 && defaultPermissionLevel != 0)
            {
                PermissionLevel = defaultPermissionLevel;
            }
		}

		/// <summary>
		/// TODO: Not implemented
		/// </summary>
		/// <param name="cachePolicy">policy to use to cache this instance</param>
		public NonStaffPerson(ICachePolicy cachePolicy) : base(cachePolicy)
		{
		}

		/// <summary>
		/// TODO: Not implemented
		/// </summary>
		/// <param name="connectionString"></param>
		/// <param name="args"></param>
		public override void Load(string connectionString, params object[] args)
		{
			throw new Exception("Not implemented");
		}

		/// <summary>
		/// Persists changes to this instance to the database. 
		/// </summary>
		/// <param name="sqlConnection">connection to use to connect to the database</param>
		protected override void SaveObject(SqlTransaction transaction)
		{
			try
			{
				Person.Save(transaction);
				AdmPersonId = Person.Id;

				if (Dirty)
					Id = (int) DataAccess.ExecuteScalar(
						transaction.Connection,
						transaction,
						"UpdateNonStaffPerson", 
						DataAccess.BuildSqlParameterArray(
						"@mapId", SqlDbType.Int, Id,
						"@protocolId", SqlDbType.Int, ProtocolId,
						"@admPersonId", SqlDbType.Int, Person.Id,
						"@accessRightBitValue", SqlDbType.Int, PermissionLevel,
						"@contactPerson", SqlDbType.Bit, IsContactPerson,
						"@comments", SqlDbType.VarChar, (Comments == string.Empty) ? (object)DBNull.Value 
						: (object)Comments));

			}
			catch(Exception e)
			{
				Utility.ExceptionReport.WriteToEventLog(
					"Save of NonStaffPerson failed", e, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("Save of NonStaffPerson failed", e);
			}
		}

		/// <summary>
		/// Removes the relationship captured by this instance from the database
		/// </summary>
		/// <param name="connectionString">connection string to database</param>
		/// <param name="sqlTransaction">transaction to use while deleting</param>
		protected override void DeleteObject(SqlTransaction sqlTransaction)
		{
			try
			{
				DataAccess.ExecuteNonQuery(
					sqlTransaction.Connection,
					sqlTransaction,
					"RemoveNonStudyStaff",
					DataAccess.BuildSqlParameterArray(
					"@protocolId", SqlDbType.Int, ProtocolId,
					"@admPersonId", SqlDbType.Int, Person.Id));
			}
			catch(Exception e)
			{
				Utility.ExceptionReport.WriteToEventLog(
					"Removal of NonStaffPerson failed", e, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("Removal of NonStaffPerson failed", e);
			}
		}

		/// <summary>
		/// Cache this instance using the prevalent cache policy.
		/// </summary>
		public override void Cache()
		{
			CachePolicy.Cache(NonStaffPersonKey, this);
		}

		/// <summary>
		/// Remove this instance from the cache using the prevalent cache policy.
		/// </summary>
		public override void UnCache()
		{
			CachePolicy.UnCache(NonStaffPersonKey);
		}
	}
}
